﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data.SqlClient;
using SqlMiM.Common.Trace;
using SqlMiM.Common.Model;
using SqlMiM.Common.Framework.Configuration;
using SqlMiM.Common.Interfaces;
using SqlMiM.Common.Themes;
using SqlMiM.Common.Framework.Options;
using SqlMiM.Common.Sql;
using MvvmFoundation.Wpf;

namespace SqlMiM.Common
{
    public class Context : INotifyPropertyChanged
    {

        private SqlConnectionStringBuilder sqlConnectionStringBuilder;
        private Server server;
        private bool isInitialized = false;
        private Messenger messenger;

        #region Singleton

        private static Context current;

        public static Context Current
        {
            get
            {
                if (current == null)
                {
                    current = new Context();
                }

                return current;
            }
        }
        
        #endregion

        /// <summary>
        /// Get or Set if the Debuger system is enabled
        /// </summary>
        public Boolean IsDebugEnabled { get; set; }

        /// <summary>
        /// Constructor
        /// </summary>
        public Context()
        {
        
        }

        internal void Initialize()
        {
            // Verify Sql Server Ce Database
            SqlCeHealth.VerifyHealth();

            // Load all configurations
            Context.Current.Configuration.Load();

            // Create Messenger
            Context.current.messenger = new Messenger();

            // Load Themes and apply current Theme
            Context.Current.Themes.Load();

            // Activate Debuger
            Context.Current.IsDebugEnabled = false;

            // Add the ThemeOptionsPages to the OptionsServices
            Context.Current.Options.Add(new ThemeOptionsPage());

        }


        /// <summary>
        /// Current SqlConnectionStringBuilder
        /// </summary>
        public SqlConnectionStringBuilder SqlConnectionStringBuilder
        {
            get {
                return sqlConnectionStringBuilder; 
            }
            set {
                if (value != sqlConnectionStringBuilder)
                {
                    sqlConnectionStringBuilder = value;
                    this.RaisePropertyChanged("SqlConnectionStringBuilder");
                }
            }
        }

        /// <summary>
        /// Current Server
        /// </summary>
        public Server Server
        {
            get { 
                return server;
            }
            set {
                if (value != server)
                {
                    server = value;
                    this.RaisePropertyChanged("Server");
                }
            }
        }


        /// <summary>
        /// internal set connection
        /// </summary>
        public void SetConnectionAndServer(SqlConnectionStringBuilder sqlConnectionStringBuilder, Server server)
        {
            
            this.SqlConnectionStringBuilder = sqlConnectionStringBuilder;
            this.Server = server;
            
            this.isInitialized = true;
        }

        /// <summary>
        /// Link to OptionsDialogService
        /// </summary>
        public OptionsService Options
        {
            get
            {
                return OptionsService.Current;
            }
        }

        /// <summary>
        /// Link to OptionsDialogService
        /// </summary>
        public ThemesServices Themes
        {
            get
            {
                return ThemesServices.Current;
            }
        }

        /// <summary>
        /// LInk to Current ConfigurationService
        /// </summary>
        public IConfigurationService Configuration
        {
            get
            {
                return ConfigurationService.Current;
            }

        }

        /// <summary>
        /// Connection to my sdf
        /// </summary>
        public string ConfigurationSqlCeConnectionString
        {
            get { return @"Data Source=|DataDirectory|\SqlMiM.sdf"; }
        }


        /// <summary>
        /// Get a new connection
        /// </summary>
        public SqlConnection GetConnection(String databaseName)
        {
            if (!this.isInitialized)
                throw new ApplicationException("No Connection String has been set on SqlMiM.Common.Context");

            this.sqlConnectionStringBuilder.InitialCatalog = databaseName;
            var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ToString());

            if (this.IsDebugEnabled)
            {
                sqlConnection.FireInfoMessageEventOnUserErrors = true;
                sqlConnection.InfoMessage += (sender, e) =>
                    {
                        Notifier.Current.Notify(new InfoMessage(e));
                    };
            }

            return sqlConnection;
        }

        /// <summary>
        /// Get a new on master
        /// </summary>
        public SqlConnection GetConnection()
        {
            if (!this.isInitialized)
                throw new ApplicationException("No Connection String has been set on SqlMiM.Common.Context");
            
            this.sqlConnectionStringBuilder.InitialCatalog = "master";
            var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ToString());

            if (this.IsDebugEnabled)
            {
                sqlConnection.FireInfoMessageEventOnUserErrors = true;
                sqlConnection.InfoMessage += (sender, e) =>
                {
                    Notifier.Current.Notify(new InfoMessage(e));
                };
            }

            return sqlConnection;
        }

        /// <summary>
        /// Get Server
        /// </summary>
        public Server GetServer()
        {
            if (!this.isInitialized)
                throw new ApplicationException("No Server has been set on SqlMiM.Common.Context");

            return this.server;
        }

        /// <summary>
        /// Messenger send messages beetween colleagues
        /// </summary>
        public Messenger Messenger
        {
            get
            {
                return messenger;
            }
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The property that has a new value.</param>
        protected virtual void RaisePropertyChanged(string propertyName)
        {

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        #endregion



    }
}
